﻿using System;
using Nofs.Net.Common.Interfaces.Library;
using biz.ritter.javapi.lang;
using Nofs.Net.nofs.metadata.interfaces;
using Nofs.Net.Common.Interfaces.Cache;
using Nofs.Net.Common.Interfaces.Domain;
using biz.ritter.javapi.util;
using Db4objects.Db4o;
using biz.ritter.javapi.util.MapNS;
using Nofs.Net.Common.Interfaces;

namespace Nofs.Net.nofs.Db4o
{

    public class DomainObjectContainerManager : IDomainObjectContainerManagerInternal
    {
        //@SuppressWarnings("unchecked")
        private Map<Class, IDomainObjectContainer> _containers;
        private IObjectContainer _db;
        private IAttributeAccessor _accessor;
        private IKeyCache _keyCache;
        private IStatMapper _statMapper;
        private IFileObjectFactory _fileObjectFactory;
        private IFileCacheManager _fileCacheManager;

        //@SuppressWarnings("unchecked")
        private DomainObjectContainerManager()
        {
            _containers = new HashMap<Class, IDomainObjectContainer>();
        }

        public DomainObjectContainerManager(
                IObjectContainer db, IStatMapper statMapper, IKeyCache keyCache,
                IFileObjectFactory fileObjectFactory, IAttributeAccessor accessor) //throws Exception 
            : this()
        {
            if (db == null)
            {
                throw new System.Exception("db is null");
            }
            _db = db;
            _statMapper = statMapper;
            _keyCache = keyCache;
            _accessor = accessor;
            _fileObjectFactory = fileObjectFactory;
        }

        public void SetFileCacheManager(IFileCacheManager cacheManager)
        {
            _fileCacheManager = cacheManager;
        }

        //@SuppressWarnings("unchecked")
        public int GetObjectCountForTesting() //throws Exception 
        {
            int count = 0;

            Entry<Class, IDomainObjectContainer>[] array = new Entry<Class, IDomainObjectContainer>[_containers.entrySet().size()];
            _containers.entrySet().toArray<Entry<Class, IDomainObjectContainer>>(array);

            foreach (Entry<Class, IDomainObjectContainer> container in array)
            {
                count += ((DomainObjectContainer)container.getValue()).GetObjectCountForTesting();
            }
            return count;
        }

        public void CleanUp() //throws Exception 
        {
            _db.Close();
            _statMapper.CleanUp(true);
        }

        //@SuppressWarnings("unchecked")
        //synchronized
        public IDomainObjectContainer GetContainer(String className) //throws Exception 
        {
            Class[] array = new Class[_containers.keySet().size()];
            _containers.keySet().toArray<Class>(array);
            foreach (Class type in array)
            {
                if (type.getSimpleName().compareTo(className) == 0)
                {
                    return (IDomainObjectContainer)GetContainer(type);
                }
            }
            throw new System.Exception("could not find type: " + className);
        }

        //@SuppressWarnings("unchecked")
        //synchronized
        public IDomainObjectContainer<object> GetContainer(Class type) //throws Exception 
        {
            IDomainObjectContainer container;
            if (_containers.containsKey(type))
            {
                container = _containers.get(type);
            }
            else
            {
                DomainObjectContainer cont = new DomainObjectContainer(_statMapper, _keyCache, _fileObjectFactory, this, _accessor, _db, type);
                cont.SetFileCacheManager(_fileCacheManager);
                container = (IDomainObjectContainer)cont;
                _containers.put(type, container);
            }
            return container;
        }

    }
}
